package fregat.base.net;

import java.io.PrintStream;
import java.net.Socket;
import java.util.ResourceBundle;

public abstract class RemoteServer extends TCPServer {
  private static ResourceBundle resource = ResourceBundle.getBundle("at.ecolog.base.net.resource");

  /**
   * Initializes the remote accept thread.
   *
   * @param port       Port, where to wait for clients
   * @param serverName Name of server (prompted when client connects)
   */
  public RemoteServer(int port, String serverName) {
    super(port);
    setName(serverName);
  }

  protected TCPClient connect(Socket clientSocket) {
    TCPClient client = new RemoteClient(clientSocket, getName());
    return client;
  }

  /**
   * The implementation of this method should process the user commands. Define
   * it synchronized as multiple client may connect.
   *
   * @param input User command
   * @param out   Stream where command output should be printed to
   */
  protected abstract void parseInput(String input, PrintStream out);

  /**
   * Default implementation for a client shutdown. May be overwritten by
   * inheriting classes to clean up.
   *
   * @param out Out stream used by client
   */
  protected void clientShutdown(PrintStream out) {
  }

  /**
   * This method is called whenever a client connects.
   *
   * @param out Out stream used by client
   */
  protected void clientConnected(PrintStream out) {
  }

  private class RemoteClient extends TCPClient {

    public RemoteClient(Socket socket, String name) {
      super(socket);
      setName(name);

      out.println(getName() + "\r");
      clientConnected(out);
    }

    protected void received(byte[] receivedData, PrintStream out) {
      String data = new String(receivedData);
      if (data.equalsIgnoreCase("EXIT")) {
        shutdown();
      } else {
        if (data.equalsIgnoreCase("?")) {
          out.println(resource.getString("RemoteServer_received_1") + "\r");
        }

        parseInput(data, out);
        out.print("\r");
      }
    }

    public void shutdown() {
      if (out != null)
        out.println("\r" +
            resource.getString("RemoteServer_received_2") +
            "\r");
      clientShutdown(out);
      clients.remove(this);

      super.shutdown();
    }
  }
}
